import { getTempPath } from "../../../../utils";
import { PlatformUserAccountExpiredError } from "../../errors";
import { Client } from "./client";
import crypto from 'node:crypto';
import path from "node:path";
import fs from 'node:fs';
import ffmpeg from 'fluent-ffmpeg';
import ffmpegPath from 'ffmpeg-static';
import ffprobePath from 'ffprobe-static';
import container from "../../../container";
import dayjs from "dayjs";

export class Application {
  constructor(accountUser) {
    this.accountUser = accountUser;
    this.client = new Client(accountUser);
  }

  setRequest(request){
    this.client.setRequest(request)
  }

  // 获取账号信息
  async getUserAccount() {
    let userLogFinderId = this.accountUser.getThirdRuturn('finderUsername')

    let response

    try {
      response = await this.client.getUserInfo(userLogFinderId);
    } catch (error) {
      console.log('douyin application getUserAccount error', error)

      throw new PlatformUserAccountExpiredError('账号已过期')
    }

    if(response.data.errCode != 0){
      throw new PlatformUserAccountExpiredError(response.data.errMsg)
    }

    return response.data.data
  }

  async syncVideoRelease(filmRelease) {
    const title = filmRelease.title || '';
    const desc = filmRelease.caption || '';
    const videoUrl = filmRelease.multimedia?.material_url;
    const formatHeight = filmRelease.multimedia?.height;
    const formatWidth = filmRelease.multimedia?.width;
    const duration = filmRelease.multimedia?.material_duration / 1000;
    const coverUrl = filmRelease.multimedia?.cover_url;
    const materialSize = filmRelease.multimedia?.material_size;
    const hashtagName = filmRelease.hashtag_name || [];

    // 定时发布
    const extraInfo = filmRelease.extra_info || {};
    const sendTime = extraInfo.sendTime || 0;
    const anchor = filmRelease.anchor || {};

    const shopComponent = anchor.shop_component;

    let member, component;

    if (shopComponent) {
      const id = shopComponent.id || '';
      let productId = shopComponent.productId || '';
      const type = Number(shopComponent.type || 1);

      if (!productId && id) {
        productId = id;
      }

      if (productId) {
        component = {
          id: productId,
          type: type || 1,
        };
        member = {
          postWithMemberZoneLink: 0,
        };
      }
    }

    if (title && this.containsSpecialChars(title)) {
      throw new Error('标题包含特殊字符，符号仅支持书名号、引号、冒号、加号、问号、百分号、摄氏度，逗号可用空格代替。');
    }

    if (title && title.length > 16) {
      throw new Error(`标题超过16字限制，当前${title.length}字。`);
    }

    if (!videoUrl) {
      throw new Error('发布素材已经被删除');
    }

    if (!coverUrl) {
      try {
       // 生成唯一路径
        const uniquePath = crypto.randomBytes(16).toString('hex');
        const outputDir = path.join(getTempPath(), 'shotstack/video');
        const converFileName = `${uniquePath}_cover.png`
        const coverPath = path.join(outputDir, converFileName);

        // 确保输出目录存在
        if (!fs.existsSync(outputDir)) {
          fs.mkdirSync(outputDir, { recursive: true });
        }

        // 使用 ffmpeg 生成封面
        await new Promise((resolve, reject) => {
          ffmpeg(videoUrl)
            .setFfmpegPath(ffmpegPath.replace('app.asar', 'app.asar.unpacked'))
            .setFfprobePath(ffprobePath.path.replace('app.asar', 'app.asar.unpacked'))
            .on('error', reject)
            .screenshots({
              count: 1,
              filename: converFileName,
              folder: outputDir
            })
            .on('end', resolve);
        });

        if (fs.existsSync(coverPath)) {
          const uploaderFactory = container.resolve('uploaderFactory');
          const videoCover = await uploaderFactory.upload(coverPath, `shotstack/video/cover/${converFileName}`)

          // 上传封面文件
          coverUrl = videoCover?.fileUrl || '';
          // 删除临时文件
          fs.unlinkSync(coverPath);
        } else {
          console.log('视频号封面生成失败', {
            coverPath,
            videoUrl,
            filmRelease
          });
        }
      } catch (error) {
        console.error('视频号封面生成错误', {
          videoUrl,
          filmRelease,
          error: {
            message: error.message,
            stack: error.stack
          }
        });
      }
    }

    if (!coverUrl) {
      throw new Error('相关素材缺少封面图片');
    }

    try {
      const uploadVideoParams = {
        file: videoUrl,
        fileSize: materialSize,
        duration,
        formatHeight,
        formatWidth,
        coverUrl,
        hashtag_name: hashtagName,
        title,
        desc,
      };

      if (component) {
        uploadVideoParams.component = component;
      }

      if (member) {
        uploadVideoParams.member = member;
      }

      let timing = 0;
      if (sendTime > 0 && sendTime > dayjs().unix()) {
        timing = sendTime;
        uploadVideoParams.effectiveTime = timing;
      }

      console.log('准备开始发布微信视频号-syncVideoRelease-参数', { uploadVideoParams });
      
      let uploadVideoResult = await this.client.uploadVideo(uploadVideoParams);
      uploadVideoResult.success = true;

      if (timing > 0) {
        uploadVideoResult.timing = timing;
      }

      console.log('准备下载视频和上传到视频号-releaseVideoResult', { uploadVideoResult });
      
      return uploadVideoResult;
    } catch (error) {
      console.error('获取上传视频号的视频失败', {
        error: error.message,
        line: error.lineNumber,
        code: error.code,
        stack: error.stack
      });
      throw new Error(`发布失败（${error.message}）`);
    }
  }

  containsSpecialChars(str) {
    // 允许的特殊字符
    const allowedChars = ['：', '+', '？', '%', '《', '》', '"', '"', '℃'];
    
    // 第一步：移除允许的特殊字符
    let strReplace = str;
    for (const char of allowedChars) {
      strReplace = strReplace.replaceAll(char, '');
    }

    // 需要检查的特殊字符
    const replaceSpecial = [
      '/', '^', '$', '%', '&',
      '*', '(', ')', '}', '{',
      '@', '#', '~', '?', '<',
      '>', ',', '|', '=', '_',
      '+', '¬', '-', '[', ']',
      '£', "'", '‘', '’', '\\/'
    ];

    // 第二步：移除所有特殊字符
    let strReplace1 = strReplace;
    for (const char of replaceSpecial) {
      strReplace1 = strReplace1.replaceAll(char, '');
    }

    // 如果两个字符串不相等，说明包含特殊字符
    if (strReplace !== strReplace1) {
      console.log('包含特殊字符-containsSpecialChars', {
        str,
        strReplace,
        strReplace1,
        hasSpecialChars: true
      });
      return true;
    }

    return false;
  }
}